package handlers

import (
	"fmt"
	"net/http"
	"strconv"
	"strings"
	"werewolf/core"

	"golang.org/x/exp/rand"
)

func ReissueHandler(w http.ResponseWriter, r *http.Request) { //  重新发牌
	fmt.Println("ReissueHandler")
	if r.Method != http.MethodGet {
		http.Error(w, "Invalid request method", http.StatusMethodNotAllowed)
		return
	}

	roomNo := r.URL.Query().Get("room")
	playNo := r.URL.Query().Get("playerNo")

	handle, err := core.Connection()
	if err != nil {
		http.Error(w, "Connection failed: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer handle.Close()

	// Start a transaction
	tx, err := handle.Begin()
	if err != nil {
		http.Error(w, "Error starting transaction: "+err.Error(), http.StatusInternalServerError)
		return
	}

	// Fetch players
	users, err := tx.Query("SELECT * FROM Player WHERE RmNo=?", roomNo)
	if err != nil {
		tx.Rollback()
		http.Error(w, "Error fetching players: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer users.Close()

	newArray := make([]int, 0)
	totalPlayers, _ := strconv.Atoi(playNo)
	newPlayer := make(map[int]int)

	for users.Next() {
		var username string
		var name string
		var oldRoomNo int
		var role string
		var idNo int
		var survival int
		var vote int

		err := users.Scan(&username, &name, &oldRoomNo, &role, &idNo, &survival, &vote)
		if err != nil {
			tx.Rollback()
			http.Error(w, "Error scanning player: "+err.Error(), http.StatusInternalServerError)
			return
		}

		newRole := rand.Intn(totalPlayers) + 1 // Generate a random role between 1 and playNo
		for contains(newArray, newRole) {
			newRole = rand.Intn(totalPlayers) + 1
		}
		newArray = append(newArray, newRole)

		newPlayer[idNo] = newRole // Store the new role for the player
	}
	ainewrole := 0
	//Update player role
	for key, value := range newPlayer {
		_, err = tx.Exec("UPDATE Player SET Role=?, Survival=1 WHERE RmNo=? AND No=?", value, roomNo, key)
		if err != nil {
			tx.Rollback()
			http.Error(w, "Error updating player role: "+err.Error(), http.StatusInternalServerError)
			return
		}
		if key == 1 { //ai存在且当前角色编号是1号，记录ai的新角色编号
			ainewrole = value
		}

	}

	var exists bool
	err = tx.QueryRow("SELECT EXISTS(SELECT 1 FROM ai_info WHERE RmNo = ?)", roomNo).Scan(&exists)
	if err != nil {
		tx.Rollback()
		http.Error(w, "Database query failed: "+err.Error(), http.StatusInternalServerError)
		return
	} //判断本局游戏中ai是否存在

	if exists {
		_, err = tx.Exec("UPDATE ai_info SET RoleInt=? WHERE RmNo=?", ainewrole, roomNo)
		if err != nil {
			tx.Rollback()
			http.Error(w, "Error updating ai role: "+err.Error(), http.StatusInternalServerError)
			return
		}

	}
	fmt.Println("success to update")
	// Fetch the role for the game
	var role string
	err = tx.QueryRow("SELECT Role FROM Game WHERE RmNo=?", roomNo).Scan(&role)
	if err != nil {
		tx.Rollback()
		http.Error(w, "Error fetching games: "+err.Error(), http.StatusInternalServerError)
		return
	}

	var enabledRoleList []string
	if role != "" {
		enabledRoleList = strings.Split(role, ";")
	}

	// Update Running table
	runners, err := tx.Query("SELECT * FROM running WHERE RmNo=?", roomNo)
	if err != nil {
		tx.Rollback()
		http.Error(w, "Error fetching running data: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer runners.Close()

	var columns []string

	if runners.Next() {
		columns, err = runners.Columns()
		if err != nil {
			tx.Rollback()
			http.Error(w, "Error fetching columns: "+err.Error(), http.StatusInternalServerError)
			return
		}
	}

	for runners.Next() {
		tx.Rollback()
		http.Error(w, "Error: More than one running data found for the room", http.StatusInternalServerError)
		return
	}

	if columns != nil {
		var clearKeys []string
		for _, key := range columns {
			for _, value := range enabledRoleList {
				if key == value {
					clearKeys = append(clearKeys, fmt.Sprintf("`%s`=0", key))
				}
			}
		}
		clearKeys = append(clearKeys, "w=0", "death1=0", "death2=0", "death3=0", "start=0", "boomable=0")

		sqlString := fmt.Sprintf("UPDATE Running SET %s WHERE RmNo=%s", strings.Join(clearKeys, ", "), roomNo)
		_, err = tx.Exec(sqlString)
		if err != nil {
			tx.Rollback()
			http.Error(w, "Error updating running data: "+err.Error(), http.StatusInternalServerError)
			return
		}
	}

	// Commit the transaction
	if err := tx.Commit(); err != nil {
		http.Error(w, "Error committing transaction: "+err.Error(), http.StatusInternalServerError)
		return
	}

	// Redirect back to the previous page
	fmt.Fprintln(w, "<script>window.history.back();</script>")
}

func contains(slice []int, item int) bool {
	for _, a := range slice {
		if a == item {
			return true
		}
	}
	return false
}
